package util.thread_pool;

import exception.UnifiedExceptionConsole;
import gnu.io.SerialPort;
import javafx.application.Platform;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.concurrent.Task;
import javafx.scene.control.Alert;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import model.SerialPortUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import util.Common;
import util.LoadConfigInfo;

import java.io.*;

public class SendFileTask extends Task<Object> {

    private final static Logger logger = LoggerFactory.getLogger(SendFileTask.class);

    /**
     * 任务名称
     */
    private final String name;

    private final File file;
    private final SerialPort serialPort;
    private Integer sendLength;
    private final Label sendDataLength;
    private final TextArea displayTextArea;

    private final LoadConfigInfo loadConfigInfo = new LoadConfigInfo();

    public SendFileTask(String name, File file, SerialPort serialPort, Integer sendLength, Label sendDataLength, TextArea displayTextArea) {
        this.name = name;
        this.file = file;
        this.serialPort = serialPort;
        this.sendLength = sendLength;
        this.sendDataLength = sendDataLength;
        this.displayTextArea = displayTextArea;
    }

    /**
     * 只读对象包装器
     */
    private ReadOnlyObjectWrapper<Integer> results =
            new ReadOnlyObjectWrapper<Integer>(this, "sendLength", this.sendLength);

    /**
     * 获取只读对象
     *
     * @return 只读对象
     */
    public final Integer getResults() {
        return results.get();
    }

    /**
     * 获取只读对象属性
     *
     * @return 对象属性
     */
    public final ReadOnlyObjectProperty<Integer> resultsProperty() {
        return results.getReadOnlyProperty();
    }

    @Override
    protected Object call() throws Exception {
        InputStreamReader reader = null;
        try {
            reader = new InputStreamReader(new FileInputStream(file), loadConfigInfo.getSerialPortSendDataCharsetName());
        } catch (Exception e) {
            UnifiedExceptionConsole.console(e);
        }
        if (reader == null) {
            Common.alert(Alert.AlertType.WARNING, "警告", "打开的文件为空文件！");
            return null;
        }
        //读取
        BufferedReader bfreader = new BufferedReader(reader);

        //获取文件行数
        FileReader fr = new FileReader(file);
        LineNumberReader lnr = new LineNumberReader(fr);

        //按行读取文件数据
        String line;
        try {
            //获取文件总行数
            Long t3 = System.currentTimeMillis();
            long fileLength = file.length();
            int linenumber = 0;
            lnr.skip(fileLength);
            linenumber = lnr.getLineNumber();
            /*while (lnr.readLine() != null){
                linenumber++;
            }*/
            Long t4 = System.currentTimeMillis();
            logger.info("文件总行数: {}", linenumber);
            logger.info("获取文件总行数耗时: {} ms", (t4 - t3));

            Long t1 = System.currentTimeMillis();
            int i = 0;
            while ((line = bfreader.readLine()) != null) {
                //Thread.sleep(1);
                if (isCancelled()) {
                    break;
                }
                i++;
                line = line + "\n";
                //注意：此处获取字符串的二进制编码格式与文件编码格式一致
                byte[] bytes = line.getBytes(loadConfigInfo.getSerialPortSendDataCharsetName());
                //按行发送数据，以文件编码格式发送数据
                SerialPortUtil.sendData(serialPort, bytes, loadConfigInfo.getSerialPortSendDataCharsetName());

                //更新实际发送的数据长度
                sendLength = sendLength + bytes.length;
                Platform.runLater(() -> {
                    //显示更新后的数据长度
                    sendDataLength.setText("Send: " + sendLength);
                });
                updateProgress(i, linenumber);
            }
            Long t2 = System.currentTimeMillis();
            logger.info("发送文件耗时: {} ms", (t2 - t1));
            Platform.runLater(() -> {
                displayTextArea.appendText("发送耗时：" + (t2 - t1) + " ms\n");
            });
        } catch (IOException ex) {
            logger.error("IOException", ex);
        }
        try {
            reader.close();
            bfreader.close();
            fr.close();
            lnr.close();
        } catch (IOException ex) {
            logger.error("IOExceptionn", ex);
        }
        results.set(sendLength);
        return sendLength;
    }

    @Override
    protected void succeeded() {
        super.succeeded();
        updateMessage("Done!");
        logger.info("{} is Done!", this);
    }

    @Override
    protected void cancelled() {
        super.cancelled();
        updateMessage("Cancelled!");
        logger.info("{} is Cancelled!", this);
    }

    @Override
    protected void failed() {
        super.failed();
        updateMessage("Failed!");
        logger.info("{} is Failed!", this);
    }

    @Override
    protected void running() {
        super.running();
        updateMessage("Running!");
        logger.info("{} is Running!", this);
    }

    @Override
    protected void scheduled() {
        super.scheduled();
        updateMessage("Scheduled!");
        logger.info("{} is Scheduled!", this);
    }

    /**
     * 获取任务名称
     *
     * @return 任务名称
     */
    public String getName() {
        return name;
    }

    @Override
    public String toString() {
        return "SendFileTask [ name = " + name + " ]";
    }

}
